SpringMVC 接收参数
获取请求参数的几种方式
参考资料 springMVC接收参数的几种形式 参考资料 目前为止全网最全的 SpringBoot 参数传递方案
使用形参来接收
Controller 中的业务方法的形参名称要与请求参数的 name 一致,参数值会自动匹配映射
这个适合 Get
请求
/**
* 直接把表单的参数写在Controller相应的方法的形参中
* @param username
* @param password
* @return
*/
@GetMapping("/addUser1")
public String addUser1(String username,String password) {
System.out.println("username is:"+username);
System.out.println("password is:"+password);
return "demo/index";
}
绑定请求参数
上面使用形参必须对应请求参数名,可以使用注解 @RequestParam
绑定请求参数到形参上
用注解 @RequestParam
绑定请求参数到方法入参, POST 方式的时候编码方式需设置为:x-www-form-urlencoded
, 不能接受 JSON
@GetMapping("/doLogin")
public User doLogin(@RequestParam(value="name") String username, @RequestParam(value="pwd") String password) {
logger.info("name: " + username);
logger.info("pwd: " + password);
User user = new User();
user.setPwd(password);
user.setName(username);
return user;
}
获取数组类型参数
Controller 中的业务方法的 数组名称与请求参数的 name 一致时,参数值会自动映射匹配
http://localhost:8080/test?strs=111&strs=222&strs=333
@RequestMapping("/test")
public String addUser1(String[] strs) {
System.out.println(Arrays.asList(strs));
}
Post 请求获取参数
关键是要使用 @RequestBody
注解来获取响应体里的内容
@PostMapping("/login")
public String login(@RequestBody User user) {
log.info(user.toString());
return "ok";
}
HttpServletRequest 获取
/**
* 2、通过HttpServletRequest接收
* @param request
* @return
*/
@RequestMapping("/addUser2")
public String addUser2(HttpServletRequest request) {
String username=request.getParameter("username");
String password=request.getParameter("password");
System.out.println("username is:"+username);
System.out.println("password is:"+password);
return "demo/index";
}
接收表单数据
@RequestBody
注解,必须与 contentType 类型application/json
配合使用。@RequestParam
注解,必须与 contentType 类型application/x-www-form-urlencoded
配合使用,其为默认类型。JSON.stringify()
把对象类型转换为字符串类型,一般配合@RequestBody
注解和 contentType 类型application/json
使用。
RestFul 风格
就是一个不同于传统那种直接 ?id=1&name=Lisa
那样带参数的请求
而是直接把这个参数写入地址里,通过自定义的方法来读取出来
# 传统
http://127.0.0.1/project?id=1&name=Lisa
# 使用RestFul风格
http://127.0.0.1/project/1/Lisa
注意:这玩意不是一种标准或者协议,只是一种风格
// http://localhost:8080/test/1/4
@Controller
public class RestFulController {
@RequestMapping("/test/{p1}/{p2}")
public String test(@PathVariable("p1") int a, @PathVariable("p2") int b, Model model) {
model.addAttribute("msg", "结果为:" + (a + b));
return "test";
}
}
获取请求头
使用
@RequestHeader
获取请求头信息
使用 @RequestHeader
可以获取请求头的信息,相当于 JavaWeb 里的 request.getHeader(name)
@RequestHeader
注解主要的属性
- value:请求头名称
- required:是否必须携带此请求头
使用例
@RequestMapping("/test")
public String test(@RequestHeader(value = "User-Agent", required = true) String headerValue) {
System.out.println(headerValue);
}
获取 Cookie
使用 @CookieValue
可以获取指定 Cookie 的值
- value:指定 cookie 的名称
- required:是否必须携带此 cookie
使用例
@RequestMapping("/test")
public String test(@CookieValue(value = "USERID", required = true) String userid) {
System.out.println(userid);
}
自定义类型转换器
注意:在后面的版本引入了 HttpMessageConverter 用来自定义转换器,具体区别看 SpringBoot 整合 MVC 那篇笔记
SpringMVC 默认已经提供了一些常用的类型转换器,例如客户端提交的字符串能自动转成 int 类型再传入形参
但是有些还需要自定义的转换器,例如传入一个日期的数据进来(例如这篇博客用的日期就是 2020-08-16
)这种情况就需要自定义类型转换器
注意:因为传入的数据全都是字符串,所以类型转换器的策略一般是优先匹配自定义的类型转换器,匹配失败换下一个转换器(官方默认的),全部转换器都匹配失败则报错
自定义类型转换器的开发步骤
1、定义转换器类实现 Converter 接口
2、在配置文件中声明转换器
3、在 <annotation-driven>
(注解驱动)中引用转换器
创建 Converter 实现类
public class DataConverter implements Converter<String, Date> {
@Override
public Date convert(String source) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = format.parse(source);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
声明这个 Converter
<!-- 注意:这个 mvc:annotation-driven 的支持是
xmlns:mvc="http://www.springframework.org/schema/mvc" 别引用错了 -->
<!--声明转换器-->
<bean id="ConversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.alsritter.converter.DataConverter"/>
</list>
</property>
</bean>
<!-- 把这个转换器加入到驱动里 -->
<mvc:annotation-driven conversion-service="ConversionService"/>
接收 JSON
当接收 JSON 形式的参数一般都是在响应体里取得的,所以需要使用 @RequestBody
注解
使用 Map
@PostMapping("/multiParameter")
public Result register(@RequestBody Map<String,Object> map){
log.info("多参数传递:{},{}",map.get("title"),map.get("content"));
//业务逻辑
return Result.ok("接收多参数成功");
}
参数封装到 Entity
Controller 中的业务方法的实体对象参数的属性名称与请求参数的 name 一致时,参数值会自动映射匹配
// 参数?key1=val1&key2=val2的方式加在url后面即可。
@RequestMapping("/doLogin")
public User doLogin(User u) {
logger.info("name: " + u.getName());
logger.info("pwd: " + u.getPwd());
User user = new User();
user.setName(u.getName());
user.setPwd(u.getPwd());
return user;
}
注意:类中属性必须为 public;且类中的属性只能比 json 中的属性多,不能少,因为 Spring 是通过 setter 方法注入进去的
接收的是复杂类型
参考资料 springmvc接收复杂类型的json数据需要注意的地方
如果接收的是普通的数据类型或者单对象,后端的方法上面什么也不需要处理,只需要将对象放入到参数上面就可以了
但是如果接收的是复杂类型,例如对象里面还包含对象或者是集合等,后端的方法参数上面只需要加上 @RequestBody
即可,但是还没有完,前端传递的时候需要加上 contentType:application/json
如下实例:
public class SignUpSave {
private Integer taskID;
private Integer skillID;
List<SignUpSave.Data> equipment = new ArrayList<SignUpSave.Data>();
/*...*/
public static class Data{
private Integer equipmentDetailID;
private Integer qty;
/*...*/
}
}
Controller 的方法:
public SignUpResult SignUp(HttpServletRequest request,@RequestBody SignUpSave signUpSave) throws Exception{
/*...*/
return signUpResult;
}
前端发送的数据:
var test = {
"TaskID": "1",
"SkillID": "1",
"Equipment": [
{
"EquipmentDetailID": "1",
"Qty": "1"
}
]
};
$.ajax({
type: "POST",
url:"...",
contentType: "application/json",
data: JSON.stringify(test),
dataType: "json",
success:function(res){
console.log(res)
}
})
接收多个对象
如果使用 SpringMvc 同客户端通信,完全使用 json 数据格式,例如 {name:"test"}
,name 为 User 类的属性值
@Controller
public class TestController{
@RequestMapping("\test")
@ResponseBody
public ReturnResult test(@RequestBody User user){
return new ReturnResult();
}
}
注意:类中属性必须为 public;且类中的属性只能比 json 中的属性多,不能少,因为 Spring 是通过 setter 方法注入进去的
但是有时接收 json 格式数据时,我们可能需要将其转换为多个对象 {user:{name:"test"},address:{location:"新华路"}}
,如果 Controller 写成下面这样则是错误的
@Controller
public class TestController{
@RequestMapping("\test")
@ResponseBody
public RetureResult test(@RequestBody User user, @RequestBody Address address){
return new ReturnResult();
}
}
如上代码,同时接收了两次对象,这样是错误的!因为 Request 的 Body 是以流的形式进行读取的,读取完一次后,便无法再次读取了
此时可使用包装类的方法来接收多个对象
class Param{
public User user;
public Address address;
}
@Controller
public class TestController{
@RequestMapping("\test")
@ResponseBody
public ReturnResult test(@RequestBody Param param){
return new ReturnResult();
}
}
获取集合对象
一般发送数组都是使用 JSON 的型式,所以直接使用实体对象接收就行了
使用 ajax 发送请求
let userList = new Array();
userList.push(username: "张三", password: '123')
userList.push(username: "李四", password: '123')
$.ajax({
type: "post",
url: "/test",
data: JSON.stringify(userList),
contentType: "application/json;charset=utf-8"
})
接收请求
@RequestMapping("/test")
public String test(@RequestBody List<User> userList) {
userList.forEach(System.out::println);
}
先创建一个类来接受集合对象
// Lombok
@Data
public class UserListData {
private List<User> userList;
}
接受参数
@PostMapping("/test")
public String test(@RequestBody UserListData list) {
list.forEach(System.out::println);
}
注:可以使用表单来发送集合
<form action="/test" method="post">
<!-- 传入数据的 name 带有下标(且名称要和 List 属性的名称一样) -->
<input type="text" name="userList[0].username">
<input type="text" name="userList[0].password">
<input type="text" name="userList[1].username">
<input type="text" name="userList[1].password">
<input type="text" name="userList[2].username">
<input type="text" name="userList[2].password">
<input type="submit" value="提交">
</form>
post 提交显示乱码
自定义的过滤器
public class EncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
// 需要把这个链传递下去,让下一个过滤器执行(如果没有过滤器了就直接传给 Controller)
chain.doFilter(request,response);
}
}
然后在 web.xml 里面注册这个 Filter
注意字符编码过滤器要使用 /*
来处理所有的请求
<filter>
<filter-name>myencoding</filter-name>
<filter-class>com.alsritter.filters.EncodingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myencoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Spring 的过滤器
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<!-- 注意这里的 /* 表示所有的请求都进行过滤 -->
<url-pattern>/*</url-pattern>
</filter-mapping>
注解的方式
前言:这种方式适合返回 json 或者 xml 这类数据时用
响应返回显示乱码
通过控制台(浏览器的F12)查看文件头里的
Content-Type: text/html;charset=ISO-8859-1
可以得知默认的返回编码是 IOS-8859-1
可以通过以下的方法解决:
注解 RequestMapping 中 produces 属性 指定响应体返回类型和编码
但是 必须要和 @ResponseBody 注解一起使用才可以 :因为不加 @ResponseBody
则是默认交给视图解析器去当作页面返回去了,设置响应体类型就莫得意义
通过 @RequestMapping
注解添加 produces = "text/html;charset=utf-8"
@RequestMapping(value = "/test1",produces = "text/html;charset=utf-8")
@ResponseBody
public String test(@RequestParam String name){
System.out.println(name);
return name;
}
但是用这种办法,这种方式适合返回 json 或者 xml 这类数据时用,且只能作用一个,所以如果要批量修改编码还是得靠下面的那种
使用 SpringMVC 带的工具
通过修改springmvc配置文件
这个主要作用于 @ResponseBody
响应,作用同方式二,只不过这个是全局的
实际就是 对注解解析添加一些工具(例如这里的消息转换器)
<mvc:annotation-driven>
<!--之所以需要在这里配置是因为这个信息转换器是针对@ResponseBody注解的-->
<mvc:message-converters>
<!--json 乱码问题配置-->
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="utf-8"/>
</bean>
<!--配置 json 映射的工具,这里使用 GSON-->
<bean class="org.springframework.http.converter.json.GsonHttpMessageConverter">
<property name="gson">
<bean class="com.google.gson.Gson"/>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
@RequestParam 和 @RequestBody 区别
POST、GET 的 @RequestBody 和 @RequestParam 区别
注解 @RequestParam 接收的参数是来自 HTTP 请求体或请求 url 的 QueryString 中。
注意:application/x-www-form-urlencoded 不能使用 @RequestBody,只能使用 @RequestParam
JSON 必须使用 @RequestBody